package com.sun.module_base.network.manager

import android.annotation.SuppressLint
import android.content.Context
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkRequest
import android.os.Build
import com.sun.module_network.utils.loge
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch

/**
 *@author:sunc
 *@time :2025/7/21 9:47
 *@desc: 网络状态管理
 * https://blog.csdn.net/tangweiguo03051987/article/details/148343745
 */


class NetworkStateManager private constructor(val context: Context) {
    /**
     * 网络状态变化回调
     */
    sealed interface NetworkStatus {
        object Available : NetworkStatus
        object Lost : NetworkStatus
        data class Changed(val type: NetworkType) : NetworkStatus
    }

    private val connectivityManager by lazy {
        context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    }
    private val _mNetworkState = MutableStateFlow<NetworkStatus>(NetworkStatus.Lost)
    val mNetworkState = _mNetworkState.asSharedFlow()

    private val callback = object : ConnectivityManager.NetworkCallback() {
        override fun onAvailable(network: Network) {
            postStatus(NetworkStatus.Available)
        }

        override fun onLost(network: Network) {
            postStatus(NetworkStatus.Lost)
        }

        override fun onCapabilitiesChanged(
            network: Network,
            networkCapabilities: NetworkCapabilities
        ) {
            val type = when {
                networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> NetworkType.WIFI
                networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> NetworkType.CELLULAR
                networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> NetworkType.ETHERNET
                else -> NetworkType.UNKNOWN
            }
            postStatus(NetworkStatus.Changed(type))
        }
    }

    private fun postStatus(status: NetworkStatus) {
        MainScope().launch { _mNetworkState.emit(status) }
    }

    fun register() {
        val request = NetworkRequest.Builder()
            .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
            .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
            .build()
        connectivityManager.registerNetworkCallback(request, callback)
    }

    fun unregister() {
        try {
            connectivityManager.unregisterNetworkCallback(callback)
        } catch (e: IllegalArgumentException) {
            //忽略未注册的异常
            e.message?.loge()
        }
    }

    /**
     * 低版本兼容 检查网络是否可用
     */
    fun checkNetWorkAvailable(): Boolean{
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
            val activeNet = connectivityManager.activeNetwork
            val capabilities = connectivityManager.getNetworkCapabilities(activeNet)
            capabilities?.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) == true &&
                    capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
        }else{
            @Suppress("DEPRECATION")
            connectivityManager.activeNetworkInfo?.isConnected == true
        }
    }

    /**
     * 检查网络质量
     */
    fun getNetWorkQuality(): NetWorkQuality{
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){
            val activeNetwork = connectivityManager.activeNetwork
            val networkCapabilities = connectivityManager.getNetworkCapabilities(activeNetwork)

            return when{
                networkCapabilities?.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING) == false-> NetWorkQuality.ROAMING
                networkCapabilities?.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED) == false-> NetWorkQuality.METERED
                networkCapabilities?.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED) == false-> NetWorkQuality.CONGESTED
                else-> NetWorkQuality.GOOD
            }
        }
        return NetWorkQuality.UNKNOWN
    }

    /**
     * 监听特定网络状态
     */
    fun observeWifiStatus(): Flow<Boolean> = mNetworkState.map {
        when(it){
            is NetworkStatus.Changed -> it.type == NetworkType.WIFI
            else -> false
        }
    }.distinctUntilChanged()

    companion object {
        @SuppressLint("StaticFieldLeak")
        @Volatile
        private var instance: NetworkStateManager? = null

        fun getInstance(context: Context): NetworkStateManager =
            instance ?: synchronized(this) {
                instance ?: NetworkStateManager(context.applicationContext).also { instance = it }
            }

    }
}